package fr.vvins.core.services;

import java.util.List;
import java.util.Map;

import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;

import fr.vvins.core.biz.exception.BizException;
import fr.vvins.core.biz.user.dto.CredentialDto;
import fr.vvins.core.biz.user.dto.FavoriteDto;
import fr.vvins.core.biz.user.dto.UserCommentDto;
import fr.vvins.core.biz.user.dto.UserContactDto;
import fr.vvins.core.biz.user.dto.UserDto;
import fr.vvins.core.biz.user.dto.UserDtoInfo;
import fr.vvins.core.biz.user.dto.UserLogDto;
import fr.vvins.core.common.TechnicalException;

/**
 * UserService is an interface for all methods related to user account management.
 * 
 * @author fguay
 */

public interface UserService {
	
	/**
	 * Validate a token and renew it.<BR>
	 * Method : <BR>
	 * Path : "/user/token?token={token}" <BR>
	 * Produces : MediaType.TEXT_PLAIN<BR>
	 * @param token
	 * @return a new token
	 * @throws BizException
	 * @throws TechnicalException
	 */
	@POST
	@Path("/token")
	@Produces(MediaType.TEXT_PLAIN)
	public String authenticate(@QueryParam("token")String token) throws BizException, TechnicalException;
	

	
	/**
	 * Create a new user account.<BR>
	 * Method : <BR>
	 * Path : "/user/create" <BR>
	 * Produces : MediaType.TEXT_PLAIN<BR>
	 * Consumes :  MediaType.APPLICATION_JSON<BR>
	 * 
	 * @param dto : user information
	 * @return a token : current user token
	 * @throws BizException
	 * @throws TechnicalException
	 */
	@PUT
	@Path("/create")
	@Produces(MediaType.APPLICATION_JSON)
	@Consumes(MediaType.APPLICATION_JSON)
	public String createUser(UserDto dto) throws BizException, TechnicalException;

	/**
	 * Generate a new token according to credential information.<BR>
	 * Method : PUT<BR>
	 * Path : "/user/token" <BR>
	 * Produces : MediaType.TEXT_PLAIN<BR>
	 * Consumes :  MediaType.APPLICATION_JSON<BR>
	 * 
	 * @param credential : credential to generate token. Credential is an interface and could be login/password model, or simple key
	 * in case of community (facebook, tweeter, etc...) authentication.
	 * @return token linked to user credential
	 * @throws BizException
	 * @throws TechnicalException
	 */
	@PUT
	@Path("/token")
	@Produces(MediaType.APPLICATION_JSON)
	@Consumes(MediaType.APPLICATION_JSON)
	public String generateToken(CredentialDto credential) throws BizException, TechnicalException;
	
	
	/**
	 * Add a new log to user associated to token.<BR>
	 * Method : PUT<BR>
	 * Path : "/user/log?token={token}" <BR>
	 * Produces : MediaType.APPLICATION_JSON<BR>
	 * Consumes :  MediaType.APPLICATION_JSON<BR>
	 * 
	 * @param token : current user token
	 * @param entity : entity name
	 * @param entityId : entity id
	 * @param actionId : a formated string : "a aimer XXXX" or "a acheter XXXX" or "a commenté XXXX" etc....
	 * @throws BizException
	 * @throws TechnicalException
	 */
	@PUT
	@Path("/log")
	public void addLog(@QueryParam("token") String token, @QueryParam("entity")String entity, @QueryParam("entityId")String entityId, @QueryParam("acionId")String actionId) throws BizException, TechnicalException;
	
	/**
	 * Return a list of user log.<BR>
	 * Method : GET<BR>
	 * Path : "/user/log?token={token}" <BR>
	 * Produces : MediaType.APPLICATION_JSON<BR>
	 * Consumes :  MediaType.APPLICATION_JSON<BR>
	 * 
	 * @param token : current user token
	 * @throws BizException
	 * @throws TechnicalException
	 */
	@GET
	@Path("/log")
	@Produces(MediaType.APPLICATION_JSON)
	public List<UserLogDto> getLastLog(@QueryParam("token") String token) throws BizException, TechnicalException;
	
	/**
	 * Add a favorite to user. Favorite could be a vigneron, vin, product, etc...<BR>
	 * Method : PUT<BR>
	 * Path : "/user/favorite/{entity}/{id}?token={token}" <BR>
	 * Produces : MediaType.APPLICATION_JSON<BR>
	 * Consumes :  MediaType.APPLICATION_JSON<BR>
	 * 
	 * @param token : current user token
	 * @param entity : type of entity (vigneron, vin, ...)
	 * @param id : Id of entity.
	 * @throws BizException
	 * @throws TechnicalException
	 */
	@PUT
	@Path("/favorite/{entity}/{id}")
	public void addFavorite(@QueryParam("token") String token, @PathParam("entity") String entity, @PathParam("id") String id) throws BizException, TechnicalException;
	

	/**
	 * Return a list of favorites.<BR>
	 * Method : GET<BR>
	 * Path : "/user/favorite?token={token}" <BR>
	 * Produces : MediaType.APPLICATION_JSON<BR>
	 * Consumes :  MediaType.APPLICATION_JSON<BR>
	 * 
	 * @param token : current user token 
	 * @return list of favorites.
	 * @throws BizException
	 * @throws TechnicalException
	 */
	@GET
	@Path("/favorite")
	@Produces(MediaType.APPLICATION_JSON)
	public List<FavoriteDto> getFavorites(@QueryParam("token") String token) throws BizException, TechnicalException;
	
	/**
	 * Return a list of favorites according to userId.<BR>
	 * Method : GET<BR>
	 * Path : "/user/favorite/{userId}?token={token}" <BR>
	 * Produces : MediaType.APPLICATION_JSON<BR>
	 * Consumes :  MediaType.APPLICATION_JSON<BR>
	 * 
	 * @param token : current user token 
	 * @param id ; target userId
	 * @return list of favorites.
	 * @throws BizException
	 * @throws TechnicalException
	 */
	@GET
	@Path("/favorite/{userId}")
	@Produces(MediaType.APPLICATION_JSON)
	public List<FavoriteDto> getUserFavorites(@QueryParam("token") String token, @PathParam("id") String userId) throws BizException, TechnicalException;
	
	/**
	 * Remove from favorite of current user.<BR>
	 * Method : DELETE<BR>
	 * Path : "/user/favorite/{entity}/{id}?token={token}" <BR>
	 * Produces : MediaType.APPLICATION_JSON<BR>
	 * Consumes :  MediaType.APPLICATION_JSON<BR>
	 * 
	 * @param token
	 * @param entity
	 * @param id
	 * @throws BizException
	 * @throws TechnicalException
	 */
	@DELETE
	@Path("/favorite/{entity}/{id}")
	public void removeFavorite(String token, String entity, String id) throws BizException, TechnicalException;
	
	/**
	 * Add new following user to current user. <BR>
	 * Method : PUT<BR>
	 * Path : "/user/following/{userId}/?token={token}" <BR>
	 * Produces : MediaType.APPLICATION_JSON<BR>
	 * Consumes :  MediaType.APPLICATION_JSON<BR>
	 * 
	 * @param token : current user token
	 * @param userId : target user
	 * @throws BizException
	 * @throws TechnicalException
	 */
	@PUT
	@Path("/following/{userId}")
	public void addFollowing(@QueryParam("token") String token, @PathParam("userId")String userId) throws BizException, TechnicalException;
	
	/**
	 * Return list of following users of current user.<BR>
	 * Method : GET<BR>
	 * Path : "/user/following?token={token}" <BR>
	 * Produces : MediaType.APPLICATION_JSON<BR>
	 * Consumes :  MediaType.APPLICATION_JSON<BR>
	 * 
	 * @param token : current user token
	 * @return list of following user.
	 * @throws BizException
	 * @throws TechnicalException
	 */
	@GET
	@Path("/following")
	@Produces(MediaType.APPLICATION_JSON)
	public List<UserDtoInfo> getFollowing(@QueryParam("token") String token) throws BizException, TechnicalException;
	
	/**
	 * Return a following users of specific userID.<BR>
	 * Method : GET<BR>
	 * Path : "/user/following/{userId}?token={token}" <BR>
	 * Produces : MediaType.APPLICATION_JSON<BR>
	 * Consumes :  MediaType.APPLICATION_JSON<BR>
	 * 
	 * @param token : current user token
	 * @param id : target user id
	 * @return : list of following user.
	 * @throws BizException
	 * @throws TechnicalException
	 */
	@GET
	@Path("/following/{userId}")
	@Produces(MediaType.APPLICATION_JSON)
	public List<UserDtoInfo> getUserFollowing(@QueryParam("token") String token, @PathParam("userId") String userId) throws BizException, TechnicalException;
	
	
	/**
	 * Return a followers users of specific userID.<BR>
	 * Method : GET<BR>
	 * Path : "/user/following/{userId}?token={token}" <BR>
	 * Produces : MediaType.APPLICATION_JSON<BR>
	 * Consumes :  MediaType.APPLICATION_JSON<BR>
	 * 
	 * @param token : current user token
	 * @param id : target user id
	 * @return : list of following user.
	 * @throws BizException
	 * @throws TechnicalException
	 */
	@GET
	@Path("/followers/{userId}")
	@Produces(MediaType.APPLICATION_JSON)
	public List<UserDtoInfo> getUserFollowers(@QueryParam("token") String token, @PathParam("userId") String userId) throws BizException, TechnicalException;

	
	
	/**
	 * Remove a following user.<BR>
	 * Method : DELETE<BR>
	 * Path : "/user/following/{userId}?token={token}" <BR>
	 * Produces : MediaType.APPLICATION_JSON<BR>
	 * Consumes :  MediaType.APPLICATION_JSON<BR>
	 * 
	 * @param token : current user token
	 * @param id ; following id to remove
	 * @throws BizException
	 * @throws TechnicalException
	 */
	@DELETE
	@Path("/following/{userId}")
	public void removeFollowing(@QueryParam("token") String token, @PathParam("userId") String userId) throws BizException, TechnicalException;
	
	/**
	 * Add new contact information for user.<BR>
	 * Method : PUT<BR>
	 * Path : "/user/contact?token={token}" <BR>
	 * Produces : MediaType.APPLICATION_JSON<BR>
	 * Consumes :  MediaType.APPLICATION_JSON<BR>
	 * 
	 * @param token : current user token
	 * @param contact
	 * @throws BizException
	 * @throws TechnicalException
	 */
	@PUT
	@Path("/contact")
	@Consumes(MediaType.APPLICATION_JSON)
	public void addContactInfo(@QueryParam("token") String token, UserContactDto contact) throws BizException, TechnicalException;
	
	/**
	 * Return all contact info of current user.<BR>
	 * Method : GET<BR>
	 * Path : "/user/contact?token={token}" <BR>
	 * Produces : MediaType.APPLICATION_JSON<BR>
	 * Consumes :  MediaType.APPLICATION_JSON<BR>
	 * 
	 * @param token : current user token
	 * @return
	 * @throws BizException
	 * @throws TechnicalException
	 */
	@GET
	@Path("/contact")
	@Consumes(MediaType.APPLICATION_JSON)
	@Produces(MediaType.APPLICATION_JSON)
	public List<UserContactDto> getContactInfo(@QueryParam("token") String token) throws BizException, TechnicalException;
	
	/**
	 * @param token : current user token.<BR>
	 * Method : POST<BR>
	 * Path : "/user/contact/{contactId}?token={token}" <BR>
	 * Produces : MediaType.APPLICATION_JSON<BR>
	 * Consumes :  MediaType.APPLICATION_JSON<BR>
	 * 
	 * @param tokent
	 * @param contactId
	 * @param contact
	 * @throws BizException
	 * @throws TechnicalException
	 */
	@POST
	@Path("/contact/{contactId}")
	@Consumes(MediaType.APPLICATION_JSON)
	@Produces(MediaType.APPLICATION_JSON)
	public void updateContactInfo(@QueryParam("token") String token,@QueryParam("contactId") String contactId, Map<String,String> properties) throws BizException, TechnicalException;
	
	/**
	 * @param token : current user token.<BR>
	 * Method : GET<BR>
	 * Path : "/user/followers?token={token}" <BR>
	 * Produces : MediaType.APPLICATION_JSON<BR>
	 * Consumes :  MediaType.APPLICATION_JSON<BR>
	 * 
	 * @return
	 * @throws BizException
	 * @throws TechnicalException
	 */
	@GET
	@Path("/followers")
	@Produces(MediaType.APPLICATION_JSON)
	public List<UserDtoInfo> getFollowers(@QueryParam("token") String token) throws BizException, TechnicalException;
	
	/**
	 * Return user information.<BR>
	 * Method : GET<BR>
	 * Path : "/user/info?token={token}" <BR>
	 * Produces : MediaType.APPLICATION_JSON<BR>
	 * Consumes :  MediaType.APPLICATION_JSON<BR>
	 * 
	 * @param token : current user token
	 * @return
	 * @throws BizException
	 * @throws TechnicalException
	 */
	@GET
	@Path("/info")
	@Produces(MediaType.APPLICATION_JSON)
	public UserDtoInfo getUserInfo(@QueryParam("token") String token) throws BizException, TechnicalException;
	
	/**
	 * Return user information.<BR>
	 * Method : GET<BR>
	 * Path : "/user/info?token={token}" <BR>
	 * Produces : MediaType.APPLICATION_JSON<BR>
	 * Consumes :  MediaType.APPLICATION_JSON<BR>
	 * 
	 * @param token : current user token
	 * @return
	 * @throws BizException
	 * @throws TechnicalException
	 */
	@GET
	@Path("/detail")
	@Produces(MediaType.APPLICATION_JSON)
	public UserDto getUser(@QueryParam("token") String token) throws BizException, TechnicalException;
	
	
	/**
	 * Update user profile.<BR>
	 * Method : POST<BR>
	 * Path : "/user/detail?token={token}" <BR>
	 * Produces : MediaType.APPLICATION_JSON<BR>
	 * Consumes :  MediaType.APPLICATION_JSON<BR>
	 * 
	 * @param token : current user token
	 * @param properties
	 * @return
	 * @throws BizException
	 * @throws TechnicalException
	 */
	@POST
	@Path("/detail")
	@Consumes(MediaType.APPLICATION_JSON)
	@Produces(MediaType.APPLICATION_JSON)
	public UserDto updateUser(@QueryParam("token") String token, Map<String,String> properties) throws BizException, TechnicalException;
	
	/**
	 * Return list of user's comments.<BR>
	 * Method : GET<BR>
	 * Path : "/user/comments?token={token}" <BR>
	 * Produces : MediaType.APPLICATION_JSON<BR>
	 * Consumes :  MediaType.APPLICATION_JSON<BR>
	 * 
	 * @param token : current user token
	 * @return list of user's comment.
	 * @throws BizException
	 * @throws TechnicalException
	 */
	@GET
	@Path("/comments")
	@Produces(MediaType.APPLICATION_JSON)
	public List<UserCommentDto> getComments(@QueryParam("token") String token)throws BizException, TechnicalException;
	
	/**
	 * Return a list of user's comments associated to userId.<BR>
	 * Method : GET<BR>
	 * Path : "/user/comment/{userId}?token={token}" <BR>
	 * Produces : MediaType.APPLICATION_JSON<BR>
	 * Consumes :  MediaType.APPLICATION_JSON<BR>
	 * 
	 * @param token : current user token
	 * @param userId : target user id
	 * @return
	 * @throws BizException
	 * @throws TechnicalException
	 */
	@GET
	@Path("/comment/{userId}")
	@Produces(MediaType.APPLICATION_JSON)
	public List<UserCommentDto> getUserComments(@QueryParam("token") String token, @PathParam("userId") String userId)throws BizException, TechnicalException;



	
}
